package com.xbongbong.crm.help;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.OptionalRangeEnum;
import com.xbongbong.paas.enums.StageTypeEnum;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.RegexUtil;
import com.xbongbong.paas.toolbox.wrap.DepartmentVO;
import com.xbongbong.paas.toolbox.wrap.RoleSimpleVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.detailtab.dto.MarketActivityEffectGetDTO;
import com.xbongbong.pro.detailtab.vo.MarketActivityEffectTargetVO;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.SaleStageEntity;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.enums.dictionary.ClueStatusEnum;
import com.xbongbong.saas.model.SaleStageModel;
import com.xbongbong.saas.service.toolbox.help.UserTeamHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.enums.DataPermissionEnum;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.join.query.HasChildQueryBuilder;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.metrics.CardinalityAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ScriptedMetricAggregationBuilder;
import org.elasticsearch.search.aggregations.support.ValuesSourceAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.existsQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author sunshaoxiang
 * @ClassName MarketActivityHelp
 * @Description 市场活动help //todo 有代码暂时放在这里
 * @Date 2022/6/16 16:02
 * @Version 1.0
 **/
@Component
public class MarketActivityHelp {

    public static final Logger LOGGER = LoggerFactory.getLogger(MarketActivityHelp.class);

    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private UserModel userModel;
    @Resource
    private EsHelper esHelper;
    @Resource
    private UserTeamHelp userTeamHelp;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private SaleStageModel saleStageModel;

    /**
     * 重构前 -> com.xbongbong.paas.help.PaasFormHelp#haveNoPermission(com.xbongbong.paas.toolbox.wrap.UserVO, java.util.List)
     * @param userVO
     * @param permissions
     * @return
     */
    public boolean haveNoPermission(UserVO userVO, List<OptionalRangeEntity> permissions) {
        Set<String> roleList = new HashSet<>();
        Set<Long> departmentSet = new HashSet<>();
        Set<String> userList = new HashSet<>();
        for(OptionalRangeEntity optionalRangeEntity: permissions) {
            if(Objects.equals(optionalRangeEntity.getProperty(), OptionalRangeEnum.DEPT.getValue())){
                if (RegexUtil.isNumber(optionalRangeEntity.getId())) {
                    departmentSet.add(Long.valueOf(optionalRangeEntity.getId()));
                }
            } else if (Objects.equals(optionalRangeEntity.getProperty(), OptionalRangeEnum.ROLE.getValue())){
                roleList.add(optionalRangeEntity.getId());
            } else if (optionalRangeEntity.getProperty().equals(OptionalRangeEnum.USER.getValue())){
                userList.add(optionalRangeEntity.getId());
            }
        }
        List<Long> deptList = departmentModel.getSubDepIdList(userVO.getCorpid(), departmentSet);
        deptList.addAll(departmentSet);
        String userId = userVO.getUserId();
        Set<RoleSimpleVO> roleSimpleVOSet = userVO.getRoleSet();
        Set<DepartmentVO> departmentVOSet = userVO.getDepSet();
        if (!userList.isEmpty()) {
            if (userList.contains(userId)) {
                return false;
            }
        }
        if (!roleList.isEmpty()) {
            for (RoleSimpleVO roleSimpleVO : roleSimpleVOSet) {
                if (roleList.contains(roleSimpleVO.getId().toString())) {
                    return false;
                }
            }
        }
        if (!deptList.isEmpty()) {
            for (DepartmentVO departmentVO : departmentVOSet) {
                if (deptList.contains(departmentVO.getId())) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 获取详情页线索列表
     *重构前 -> com.xbongbong.saas.help.DetailTabDataPermissionHelp#detailTeamBoolQueryParamPermission(org.elasticsearch.index.query.BoolQueryBuilder, java.lang.String, java.lang.Long, java.lang.Integer, java.lang.Integer, com.xbongbong.paas.toolbox.wrap.UserVO, com.xbongbong.paas.enums.IndexTypeEnum)
     * @param boolQueryBuilder
     * @param corpid
     * @param formId
     * @param businessType
     * @param linkBusinessType
     * @param userVO
     */
    public void detailTeamBoolQueryParamPermission(BoolQueryBuilder boolQueryBuilder, String corpid, Long formId, Integer businessType, Integer linkBusinessType, UserVO userVO,
                                                   IndexTypeEnum indexTypeEnum) throws XbbException {
        //表单共享标识，true：共享  false：隔离
        boolean formShareTag = returnFormShareTag(corpid, formId, businessType);
        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(userVO, userEntity);
        Integer dataPermission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, linkBusinessType, 0L);
        if (userVO.isAdminOrBoss()
                || (Objects.nonNull(dataPermission) && Objects.equals(DataPermissionEnum.ALL.getCode(),dataPermission))
                || formShareTag) {
            return;
        }
        List<String> userIdIn = userModel.getSubIdListByDataPermission(dataPermission, userVO.getUserId(), userVO.getCorpid(), BasicConstant.ONE,false);
        HasChildQueryBuilder hasChildQueryBuilder = esHelper.teamQueryBuilder(indexTypeEnum , userVO.getCorpid(), null, userIdIn);
        boolQueryBuilder.must(hasChildQueryBuilder);
    }

    /**
     * 返回表单共享标识
     * 重构前 -> com.xbongbong.saas.help.DetailTabDataPermissionHelp#returnFormShareTag(java.lang.String, java.lang.Long, java.lang.Integer)
     * @param corpid 公司id
     * @param formId 表单id
     * @param businessType 业务类型
     * @return true:共享  false:隔离
     */
    private boolean returnFormShareTag(String corpid, Long formId, Integer businessType) throws XbbException {
        //表单共享标识，true：共享  false：隔离
        boolean formShareTag = userTeamHelp.getFormShareTag(corpid, formId, businessType);
        return formShareTag;
    }

    /**
     * 返回活动成效相关指标
     * 重构前 -> com.xbongbong.saas.help.SaasGetHelp#getMarketActivityEffectTargetVO(com.xbongbong.pro.detailtab.dto.MarketActivityEffectGetDTO)
     * @param marketActivityEffectGetDTO
     * @return
     * @throws XbbException
     */
    public MarketActivityEffectTargetVO getMarketActivityEffectTargetVO(MarketActivityEffectGetDTO marketActivityEffectGetDTO) throws XbbException {
        MarketActivityEffectTargetVO marketActivityEffectTargetVO = new MarketActivityEffectTargetVO();
        //“线索数量”，“有效线索数量”,"转化线索数量","客户数量" , "线索转客户转化率" （五个指标）
        setClueAndCustomerTarget(marketActivityEffectGetDTO, marketActivityEffectTargetVO);
        List<Long> transformedCustomerIds = marketActivityEffectGetDTO.getTransformedCustomerIds();
        List<Long> transformedClueIds = marketActivityEffectGetDTO.getTransformedClueIds();
        if(CollectionsUtil.isNotEmpty(transformedCustomerIds) && CollectionsUtil.isNotEmpty(transformedClueIds)) {
            //线索转机会转化率
            setClueOpportunityRateTarget(marketActivityEffectGetDTO.getCorpid(),transformedClueIds,marketActivityEffectTargetVO);
            //setLinkOpportunityCustomerCount(marketActivityEffectGetDTO, transformedCustomerIds, marketActivityEffectTargetVO);
            //"机会数量""机会金额""赢单机会数""赢单机会金额" （四个指标）
            setLinkOpportunityTarget(marketActivityEffectGetDTO, transformedCustomerIds, marketActivityEffectTargetVO);
        }
        return marketActivityEffectTargetVO;

    }

    /**
     * 设置线索和客户相关的指标
     * 重构前 -> com.xbongbong.saas.help.SaasGetHelp#setClueAndCustomerTarget(com.xbongbong.pro.detailtab.dto.MarketActivityEffectGetDTO, com.xbongbong.pro.detailtab.vo.MarketActivityEffectTargetVO)
     * @return
     */
    private void setClueAndCustomerTarget(MarketActivityEffectGetDTO marketActivityEffectGetDTO , MarketActivityEffectTargetVO marketActivityEffectTargetVO ) throws XbbException {
        List<Long> customerIds = null;
        List<Long> transformedClueIds = null;
        List<Long> clueIds = new ArrayList<>();
        Long marketActivityId = marketActivityEffectGetDTO.getDataId();
        String corpId = marketActivityEffectGetDTO.getCorpid();
        UserVO loginUser = marketActivityEffectGetDTO.getLoginUser();

        Integer clueCount = 0 ;
        Integer effectiveClueCount = 0;
        Integer transformedClueCount = 0;
        Integer customerCount =0;


        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpId));
        boolQueryBuilder.filter(termQuery(ClueEnum.getEsAttr4Keyword(ClueEnum.MARKET_ACTIVITY_ID),marketActivityId));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        //添加角色数据权限过滤
        detailTeamBoolQueryParamPermission(boolQueryBuilder, corpId, marketActivityEffectGetDTO.getFormId(), marketActivityEffectGetDTO.getBusinessType(),
                XbbRefTypeEnum.CLUE.getCode(), loginUser, IndexTypeEnum.IDX_SAAS_CLUE_TEAM);
        //setDataPermission(loginUser,boolQueryBuilder,IndexTypeEnum.IDX_SAAS_CLUE_TEAM, null);
        //添加"表单权限"过滤
        setFormPermission(loginUser,boolQueryBuilder);
        sourceBuilder.query(boolQueryBuilder);
        //按照线索状态分组聚合
        ValuesSourceAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("aggs01").field(ClueEnum.getEsAttr4Keyword(ClueEnum.CLUE_STATUS)).size(Integer.MAX_VALUE);
        //自定义脚本聚合,分组后组内聚合 线索id ，返回到一个数组中，用于查询客户.
        /*
         * scripted_metric" : {
         *  "init_script": "state.clueIds=[]",
         *             "map_script": ""doc.dataId.value == null ? null : state.clueIds.add(doc.dataId.value)"",
         *             "combine_script": "state.clueIds",
         *             "reduce_script": "states.stream().flatMap(Collection::stream).toArray()" //注意这里是 states 比上面多了一个 s
         *           }
         *
         */
        ScriptedMetricAggregationBuilder scriptedMetricAggregationBuilder = AggregationBuilders
                .scriptedMetric("agg")
                .initScript(new Script("state.clueIds = []"))
                .mapScript(new Script("doc.dataId.value == null ? null : state.clueIds.add(doc['"+ StringConstant.DATA_ID +"'].value)"))
                .combineScript(new Script("state.clueIds"))
                //注意这里是 states 比上面多了一个 s
                .reduceScript(new Script("states.stream().flatMap(Collection::stream).toArray()"));
        termsAggregationBuilder.subAggregation(scriptedMetricAggregationBuilder);
        JSONObject resultJsonObject;
        try{
            resultJsonObject = esHelper.elasticAggs4Buckets2Object(IndexTypeEnum.IDX_SAAS_CLUE, boolQueryBuilder, termsAggregationBuilder);
        }catch (Exception e){
            LOGGER.error("SaasGetHelp  getClueCountAndCustomerIds 查询es 发生异常,错误 boolQueryBuilder-{}-,termsAggregationBuilder-{}-",boolQueryBuilder.toString(),termsAggregationBuilder.toString());
            //直接返回
            return;
        }
        // buckets 的结果，数据结构如下，数据节点层级的是在 esHelper 中 设置好的)
           /*
        "aggregations": {
            "aggs01": {
                "doc_count_error_upper_bound": 0,
                        "sum_other_doc_count": 0,
                        "buckets": [
                            {
                                "key": "1",  ##  key 是 线索阶段Code （ClueEnum.CLUE_STATUS text_5 ）,线索阶段 ClueStatusEnum
                                "doc_count": 2,
                                "aggs02": {
                                "value": [   ## value 是一个数组，存放的是线索关联的客户的id （ClueEnum.CUSTOMER_ID text_11）
                                    "2",
                                    "1"
                                ]
                            }
                            },
                            {
                                "key": "2",
                                "doc_count": 1,
                                "aggs02": {
                                "value": [
                                "3"
                                ]
                            }
                            },
                            {
                                "key": "3",
                                "doc_count": 1,
                                "aggs02": {
                                "value": [
                                null
                                ]
                            }
                            }
                            ]
            }
        }
         */
        if(Objects.nonNull(resultJsonObject)){
            //数据节点结构在上面注释中
            JSONArray bucketsArray = resultJsonObject.getJSONArray("buckets");
            if(Objects.nonNull(bucketsArray)){
                for (Object object : bucketsArray) {
                    if(object!=null){
                        JSONObject json = (JSONObject) object;
                        //线索状态对应的code值
                        String statusCode = json.getString("key");
                        //该线索状态的线索数
                        Integer count = json.getInteger("doc_count");
                        //线索总数 = 不同状态的线索数据总和
                        clueCount += count;
                        //有效线索数 = 不是无效状态的线索数总和
                        if(!statusCode.equals(ClueStatusEnum.INVALID.getCode())){
                            effectiveClueCount += count;
                        }
                        //转换线索数 = 状态为"已转换"的线索总数
                        if(statusCode.equals(ClueStatusEnum.TRANSFORMED.getCode())){
                            transformedClueCount += count;

                        }
                        //获取线索id，用于查询客户
                        JSONObject aggs02 = json.getJSONObject("scripted_metric#agg");
                        if(Objects.nonNull(aggs02)){
                            JSONArray clueIdsArray = aggs02.getJSONArray("value");
                            if(Objects.nonNull(clueIdsArray) &&  clueIdsArray.size()>0){
                                List<Long> ids = JSONArray.parseArray(clueIdsArray.toJSONString(), Long.class);
                                List<Long> clueIdList = ids.stream().distinct().filter(id -> Objects.nonNull(id)).collect(toList());
                                if(statusCode.equals(ClueStatusEnum.TRANSFORMED.getCode())){
                                    //获取已转换的线索id集合
                                    transformedClueIds  = clueIdList;
                                }
                                //去重，过滤空
                                clueIds.addAll(clueIdList);
                            }
                        }

                    }
                }

            }

        }
        //获取线索转化的客户数据（通过已转换的线索id去关联查询）
        if(CollectionsUtil.isNotEmpty(clueIds)){
            BoolQueryBuilder boolQuery = boolQuery();
            boolQuery.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpId));
            boolQuery.filter(termsQuery(CustomerManagementEnum.getEsAttr4Keyword(CustomerManagementEnum.CLUE_ID),clueIds));
            boolQuery.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            List<PaasFormDataEntityExt> customerDataList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CUSTOMER, boolQuery, PaasFormDataEntityExt.class, Arrays.asList(StringConstant.DATA_ID));
            if(CollectionsUtil.isNotEmpty(customerDataList)){
                customerIds = customerDataList.stream().map(item->item.getDataId()).collect(Collectors.toList());
            }

        }
        //线索转客户转化率
        if(CollectionsUtil.isNotEmpty(customerIds) && clueCount > 0){
            customerCount = customerIds.size();
            DecimalFormat df = new DecimalFormat("0.00");
            marketActivityEffectTargetVO.setClueCustomerRate(df.format(((double) customerCount / clueCount) * 100));
        }
        marketActivityEffectTargetVO.setClueCount(clueCount);
        marketActivityEffectTargetVO.setEffectiveClueCount(effectiveClueCount);
        marketActivityEffectTargetVO.setTransformedClueCount(transformedClueCount);
        marketActivityEffectTargetVO.setCustomerCount(customerCount);
        //封装查询条件,用于计算客户和机会相关的指标
        marketActivityEffectGetDTO.setTransformedClueIds(transformedClueIds);
        marketActivityEffectGetDTO.setTransformedCustomerIds(customerIds);
    }

    /**
     * 设置表单权限
     * 重构前 -> com.xbongbong.saas.help.SaasGetHelp#setClueOpportunityRateTarget(java.lang.String, java.util.List, com.xbongbong.pro.detailtab.vo.MarketActivityEffectTargetVO)
     * @param userVO
     * @param boolQueryBuilder
     */
    private void setFormPermission(UserVO userVO,BoolQueryBuilder boolQueryBuilder){
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", userVO.getCorpid());
        param.put("businessType", XbbRefTypeEnum.CLUE.getCode());
        param.put("enable", 1);
        param.put("del", DelEnum.NORMAL.getDel());
        List<PaasFormEntityExt> list = paasFormModel.list(param);
        Boolean noPermission;
        //获取用户有使用权限的表达 id集合
        List<Long> formIdIn = new ArrayList<>();
        if(CollectionsUtil.isNotEmpty(list)){
            for(PaasFormEntityExt paasFormEntityExt : list){
                List<OptionalRangeEntity> optionalRangeList = JSONObject.parseArray(paasFormEntityExt.getPermission(), OptionalRangeEntity.class);
                noPermission  = CollectionsUtil.isNotEmpty(optionalRangeList) && haveNoPermission(userVO, optionalRangeList);
                //去除没有使用权限的表单,noPermission为true  表示没有使用权限
                if (!noPermission) {
                    formIdIn.add(paasFormEntityExt.getId());
                }
            }
        }
        if(CollectionsUtil.isNotEmpty(formIdIn)){
            boolQueryBuilder.filter(termsQuery("formId",formIdIn));
        }else {
            //没有使用权限的表单 传输-1
            boolQueryBuilder.filter(termQuery("formId",-1));
        }
    }


    /**
     * 设置线索机会转化率
     * 重构前 -> com.xbongbong.saas.help.SaasGetHelp#setClueOpportunityRateTarget(java.lang.String, java.util.List, com.xbongbong.pro.detailtab.vo.MarketActivityEffectTargetVO)
     */
    private void setClueOpportunityRateTarget(String corpId, List<Long> clueIds,MarketActivityEffectTargetVO marketActivityEffectTargetVO){
        Integer linkOpportunityClueCount = 0;
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpId));
        boolQueryBuilder.filter(termsQuery("clueId", clueIds));
        boolQueryBuilder.must(existsQuery("saleOpportunityId"));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        sourceBuilder.query(boolQueryBuilder);
        /*
        去重聚合
        请求信息
        "aggs" : {
        "distinct_colors" : {
            "cardinality" : {
              "field" : "data.text_11"
            }
          }
        }
        响应信息
        "aggregations": {
            "aggs01": {
                "value": 5
            }
        }
        */
        //去重聚合(clueId去重)
        CardinalityAggregationBuilder cardinalityAggregationBuilder = AggregationBuilders.cardinality("aggs01").field("clueId");
        JSONObject resultJsonObject;
        try{
            resultJsonObject = esHelper.multElasticAggs4NoBuckets2Object(IndexTypeEnum.IDX_STATICS_MARKET_DATA, boolQueryBuilder, Arrays.asList(cardinalityAggregationBuilder));
        }catch (Exception e){
            LOGGER.error("SaasGetHelp  linkOpportunityCustomerCount 查询es 发生异常,错误 boolQueryBuilder-{}-,cardinalityAggregationBuilder-{}-",boolQueryBuilder.toString(),cardinalityAggregationBuilder.toString());
            //直接返回 0
            return;
        }
        JSONObject aggregations = resultJsonObject.getJSONObject("aggregations");
        if(Objects.nonNull(aggregations)){
            JSONObject aggs01 = aggregations.getJSONObject("aggs01");
            if(Objects.nonNull(aggs01)){
                linkOpportunityClueCount = Objects.isNull(aggs01.getInteger("value")) ? 0 : aggs01.getInteger("value");
                if(linkOpportunityClueCount > 0){
                    //设置 线索转机会转化率 （ （1）公式 = 已转机会的线索数 / 线索总数 (2) 已转机会的线索数:线索转客户，客户下有机会，这条线索才算;(3)三表查询，太难了，直接用国徽的数据了）
                    DecimalFormat df = new DecimalFormat("0.00");
                    String  clueOpportunityRate = df.format(((double) linkOpportunityClueCount / marketActivityEffectTargetVO.getClueCount()) * 100);
                    marketActivityEffectTargetVO.setClueOpportunityRate(clueOpportunityRate);
                }
            }
        }
    }

    /**
     * 返回 活动成效 ，机会相关的指标
     *重构前 -> com.xbongbong.saas.help.SaasGetHelp#setLinkOpportunityTarget(com.xbongbong.pro.detailtab.dto.MarketActivityEffectGetDTO, java.util.List, com.xbongbong.pro.detailtab.vo.MarketActivityEffectTargetVO)
     * @param marketActivityEffectGetDTO
     * @param customerIdList
     * @return
     * @throws XbbException
     */
    private void  setLinkOpportunityTarget(MarketActivityEffectGetDTO marketActivityEffectGetDTO, List<Long> customerIdList, MarketActivityEffectTargetVO marketActivityEffectTargetVO) throws XbbException {
        Double allOpportunityAmount =  0.00;
        Integer allOpportunityCount = 0;
        Double winOpportunityAmount  = 0.00;
        Integer winOpportunityCount = 0;
        //按照"机会阶段"分组,对机会金额求和
        BoolQueryBuilder  boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, marketActivityEffectGetDTO.getCorpid()));
        boolQueryBuilder.filter(termsQuery(SalesOpportunityEnum.getEsAttr4Keyword(SalesOpportunityEnum.CUSTOMER_NAME), customerIdList));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
//        ValuesSourceAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("aggs01").field(SalesOpportunityEnum.getEsAttr4Keyword(SalesOpportunityEnum.SALE_STAGE)).size(Integer.MAX_VALUE);
        ValuesSourceAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("aggs01").field(SalesOpportunityEnum.getEsAttr4Keyword(SalesOpportunityEnum.STAGE_ID)).size(Integer.MAX_VALUE);
        // 对每组的 data.num_2  求和（机会金额）
        termsAggregationBuilder.subAggregation(AggregationBuilders.sum("costTotal").field(SalesOpportunityEnum.getEsAttr4Keyword(SalesOpportunityEnum.ESTIMATE_AMOUNT)));
        JSONObject resultJsonObject = null;
        try{
            resultJsonObject = esHelper.elasticAggs4Buckets2Object(IndexTypeEnum.IDX_SAAS_OPPORTUNITY, boolQueryBuilder, termsAggregationBuilder);
        }catch (Exception e){
            //发生异常，返回 机会数量为 0
            LOGGER.error("getLinkOpportunity,es 查询机会指标发生异常",e.getMessage());
            return ;
        }
        JSONArray oppoBucketsArray = resultJsonObject.getJSONArray("buckets");
        if(oppoBucketsArray != null){
            List<SaleStageEntity> saleStageList = saleStageModel.getList(marketActivityEffectGetDTO.getCorpid(), null, null, StageTypeEnum.SUCCESS_STAGE.getType());
            List<Long> saleStageIdList = saleStageList.stream().map(SaleStageEntity::getId).collect(Collectors.toList());
            for(Object object : oppoBucketsArray){
                if(object != null){
                    //判断空
                    JSONObject json = (JSONObject) object;
                    //key 是 机会阶段
//                    Integer stageCode = json.getInteger("key");
                    Integer count = FastJsonHelper.getIntegerOrDefaultFromFormData(json , "doc_count" , 0);
                    Double value = FastJsonHelper.getDoubleOrDefaultFromFormData(json.getJSONObject("costTotal"), "value", 0.00);
                    allOpportunityAmount += value;
                    allOpportunityCount += count;
                    //赢单阶段
                    // 【按照stageId聚合统计，阶段id是否为成功阶段】
//                    if(Integer.valueOf(SaleStageEnum.DEAL.getCode()).equals(stageCode)){
//                        winOpportunityAmount += value;
//                        winOpportunityCount += count;
//                    }
                    Long stageId = json.getLong("key");
                    if (saleStageIdList.contains(stageId)) {
                        winOpportunityAmount += value;
                        winOpportunityCount += count;
                    }
                }
            }
        }
        marketActivityEffectTargetVO.setAllOpportunityCount(allOpportunityCount);
        marketActivityEffectTargetVO.setAllOpportunityAmount(allOpportunityAmount);
        marketActivityEffectTargetVO.setWinOpportunityAmount(winOpportunityAmount);
        marketActivityEffectTargetVO.setWinOpportunityCount(winOpportunityCount);
    }
}
